package com.boarsoft.rpc.generalize;

import java.util.Map;

import com.boarsoft.common.util.StringUtil;
import com.boarsoft.rpc.RpcConfig;
import com.boarsoft.rpc.adapter.RpcProtocolAdapter;
import com.boarsoft.rpc.bean.RpcFaceConfig;
import com.boarsoft.rpc.bean.RpcMethodConfig;
import com.boarsoft.rpc.bean.RpcReferenceConfig;
import com.boarsoft.rpc.core.RpcContext;
import com.boarsoft.rpc.core.RpcCore;
import com.boarsoft.rpc.core.RpcInvoker;
import com.boarsoft.rpc.core.RpcLink;

public class RpcGenInvoker {

	/**
	 * 
	 * @param rmc
	 * @param args
	 * @return
	 * @throws Throwable
	 */
	public static Object invoke(RpcMethodConfig rmc, Object[] args) throws Throwable {
		return invoke((RpcReferenceConfig) rmc.getFaceConfig(), rmc, args);
	}

	/**
	 * 
	 * @param rc
	 * @param rmc
	 * @param args
	 * @return
	 * @throws Throwable
	 */
	public static Object invoke(RpcReferenceConfig rc, RpcMethodConfig rmc, Object[] args) throws Throwable {
		RpcCore rpcCore = RpcCore.getCurrentInstance();
		RpcContext rpcContext = rpcCore.getRpcContext();
		//
		String protocol = rc.getProtocol();
		if (!RpcFaceConfig.PROTOCOL_DEFAULT.equals(protocol)) {
			String bn = RpcConfig.getString("rpc.protocol.".concat(protocol), null);
			if (StringUtil.isEmpty(bn)) {
				throw new RuntimeException("Please config protocol adapter: ".concat(bn));
			}
			RpcProtocolAdapter pra = rpcContext.getBean(bn, RpcProtocolAdapter.class);
			return pra.invoke(rc, rmc, args);
		}
		// 明确是泛化调用
		// rc.setGeneralized(true);
		// 如果有指定注册中心适配器，则通过该适配器到远程注册中心注册服务引用，以获得服务提供者
		String regProvider = RpcConfig.getString("rpc.registry.adapter", null);
		if (StringUtil.isEmpty(regProvider)) {
			// 检查此服务是否有注册引用
			Map<String, RpcReferenceConfig> rm = rpcContext.getMyRegistry().getReferenceMap();
			if (!rm.containsKey(rc.getId())) {
				synchronized (rm) {
					if (!rm.containsKey(rc.getId())) {
						// 更新referenceMap，并即时到注册中心查询服务提供者注册表
						rm.put(rc.getId(), rc);
						RpcLink lo = rpcCore.link2(RpcCore.getMasterHost());
						lo.popRegistry();
					}
				}
			}
		} else {
			RpcProtocolAdapter pra = rpcContext.getBean(regProvider, RpcProtocolAdapter.class);
			// 此方法会阻塞最多3000ms，直到收到注册中心的服务提供者信息
			pra.subscribe(rc, true);
		}
		RpcInvoker invoker = new RpcInvoker(rc, rpcCore, rpcContext);
		return invoker.invoke(rmc, args, null);
	}

}
